#include "pch.h"
#include "Random.h"
#include "SpaceRock.h"
#include "SoundManager.h"

namespace
{
   dxroids::SpaceRock::Style random_style()
   {
      dxroids::Random rand;
      return static_cast<dxroids::SpaceRock::Style>(rand.Next(0, 3));
   }

   struct traits : public dxroids::GameObject::basic_traits
   {
      std::vector<D2D1_POINT_2F> points;
      float scale;
   };

   traits get_traits(dxroids::SpaceRock::Size _size, dxroids::SpaceRock::Style _style)
   {
      traits t;
      t.bounding_radius = 60.0f;  
      switch (_style)
      {
      case dxroids::SpaceRock::Style::A:  
         t.points.push_back(D2D1::Point2F(-20.0f, -40.0f));
         t.points.push_back(D2D1::Point2F(-40.0f, -20.0f));   
         t.points.push_back(D2D1::Point2F(-40.0f, 20.0f));
         t.points.push_back(D2D1::Point2F(-20.0f, 40.0f));
         t.points.push_back(D2D1::Point2F(12.0f, 40.0f)); // 5
         t.points.push_back(D2D1::Point2F(40.0f, 20.0f));
         t.points.push_back(D2D1::Point2F(32.0f, 0.0f));
         t.points.push_back(D2D1::Point2F(40.0f, -20.0f));
         t.points.push_back(D2D1::Point2F(21.0f, -40.0f));
         t.points.push_back(D2D1::Point2F(0.0f, -20.0f));  // 10       
         break;
      case dxroids::SpaceRock::Style::B:
         t.points.push_back(D2D1::Point2F(-20.0f, -39.0f));
         t.points.push_back(D2D1::Point2F(-40.0f, -20.0f));   
         t.points.push_back(D2D1::Point2F(-30.0f, -0.0f));
         t.points.push_back(D2D1::Point2F(-40.0f, 20.0f));
         t.points.push_back(D2D1::Point2F(-20.0f, 40.0f));
         t.points.push_back(D2D1::Point2F(-10.0f, 31.0f));
         t.points.push_back(D2D1::Point2F(22.0f, 35.0f));
         t.points.push_back(D2D1::Point2F(40.0f, 10.0f));
         t.points.push_back(D2D1::Point2F(22.0f, -9.0f));
         t.points.push_back(D2D1::Point2F(40.0f, -20.0f));
         t.points.push_back(D2D1::Point2F(22.0f, -40.0f));
         t.points.push_back(D2D1::Point2F(0.0f, -31.0f));
         break;
      case dxroids::SpaceRock::Style::C:
         t.points.push_back(D2D1::Point2F(-19.0f, -40.0f));
         t.points.push_back(D2D1::Point2F(-10.0f, -20.0f));
         t.points.push_back(D2D1::Point2F(-40.0f, -20.0f));
         t.points.push_back(D2D1::Point2F(-40.0f, 9.0f));
         t.points.push_back(D2D1::Point2F(-20.0f, 40.0f));
         t.points.push_back(D2D1::Point2F(11.0f, 31.0f));
         t.points.push_back(D2D1::Point2F(21.0f, 44.0f));
         t.points.push_back(D2D1::Point2F(40.0f, 20.0f));
         t.points.push_back(D2D1::Point2F(12.0f, 0.0f));
         t.points.push_back(D2D1::Point2F(40.0f, -10.0f));
         t.points.push_back(D2D1::Point2F(40.0f, -20.0f));
         t.points.push_back(D2D1::Point2F(11.0f, -40.0f));
         break;
      default:
         DxRoidsAssert(false);
      }
      
      switch (_size)
      {
      case dxroids::SpaceRock::Big:         
         t.scale = 1.2f;         
         break;
      case dxroids::SpaceRock::Medium:
         t.scale = 0.8f;         
         break;
      case dxroids::SpaceRock::Small:
         t.scale = 0.25f;         
         break;
      default:
         DxRoidsAssert(false);
      }
      return t;
   }
}

dxroids::SpaceRock::SpaceRock(Vector _pos, Size _size, Style _style)
   : GameObject(_pos, get_traits(_size, _style).bounding_radius, get_traits(_size, _style).scale)
   , size_(_size)
   , style_(_style)   
{

}

dxroids::SpaceRock::~SpaceRock()
{
   gemoetry_.Release();
}


DXROIDS_COM_PTR<ID2D1Geometry> dxroids::SpaceRock::CreateGeometry(
   DXROIDS_COM_PTR<ID2D1Factory> const &  _factory, float _scale)
{   
   traits t = get_traits(size_, style_); 
   return CreateScaledPathGeometry(_factory, t.points, _scale);   
}

dxroids::SpaceRock::Pair dxroids::SpaceRock::Break(std::shared_ptr<SoundManager> const & _sound_manager)
{    
    switch (size_)
    {
    case Size::Big:
       _sound_manager->Play(SoundEffect::BangLarge, false); 
       break;
    case Size::Medium: 
       _sound_manager->Play(SoundEffect::BangMedium, false); 
       break;
    case Size::Small: 
       _sound_manager->Play(SoundEffect::BangSmall, false); 
       break;
    }
    SetIsActive(false);
    return std::make_pair(CloneAndShrink(), CloneAndShrink());    
}

std::unique_ptr<dxroids::SpaceRock> dxroids::SpaceRock::CloneAndShrink()
{
   if (size_ == SpaceRock::Size::Small)
   {
      return std::unique_ptr<dxroids::SpaceRock>();
   }

   Random rand;

   dxroids::Vector v = GetVelocity();
   float rot = rand.NextFloat(0.0f, DXROIDS_MATH_PI_OVER_4);
   int32_t const left_or_right = rand.Next(0, 10000);
   if (left_or_right % 2 == 0)
   {
      rot *= -1;
   }  
   v.Rotate(rot);

   dxroids::Vector const & p = GetPosition();
   dxroids::SpaceRock::Size size;
   if (size_ ==  SpaceRock::Size::Big)
   {
      size = SpaceRock::Size::Medium;
   }
   else if (size_ == SpaceRock::Size::Medium)
   {
      size = SpaceRock::Size::Small;
   }
   else
   {
      DxRoidsAssert(false);
   }
   dxroids::SpaceRock::Style style = random_style();   
   std::unique_ptr<dxroids::SpaceRock> clone(new dxroids::SpaceRock(p, size, style));
   clone->SetVelocity(v);
   clone->Initialize(dxroids::GetDirect2DFactory());
   clone->SetIsActive(true);
   return clone;
}